package jdk8.stream.sream1;

import jdk8.lambda.lambda2.Employee;
import jdk8.lambda.lambda2.EmployeeData;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author Aunean
 * @date 2022/1/13 21:16
 */
/*
测试 Stream 的中间操作
 */
public class StreamAPITest1 {

    //1.筛选与切片
    @Test
    public void test1() {
        List<Employee> employees = EmployeeData.getEmployees();

        //filter(Predicate p)：接收 Lambda，从流中排除某些元素
        Stream<Employee> stream = employees.stream();
        stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);

        System.out.println("***************************");

        //limit(long maxSize)：截断流，使其元素不超过给定数量
        Stream<Employee> stream2 = employees.stream();
        Stream<Employee> limit = stream2.limit(5);
        limit.forEach(System.out::println);
        //System.out.println(Arrays.toString(limit.toArray()));

        //skip(long n)：跳过元素，返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个，则返回一个空流。与 limit(n) 互补
        Stream<Employee> stream3 = employees.stream();
        stream3.skip(3).forEach(System.out::println);

        System.out.println("***************************************");
        employees.add(new Employee(1001, "马化腾", 34, 6000.38));
        employees.add(new Employee(1001, "马化腾", 34, 6000.38));
        employees.add(new Employee(1001, "马化腾", 34, 6000.38));
        employees.add(new Employee(1001, "马化腾", 34, 6000.38));
        employees.forEach(System.out::println);

        System.out.println("*****************************");
        //distinct()：筛选，通过流所生成元素的 hashCode() 和 equals() 去除重复元素
        Stream<Employee> stream4 = employees.stream();
        stream4.distinct().forEach(System.out::println);
    }

    //映射
    @Test
    public void test2() {
        //map(Function f)：接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素
        List<String> list = Arrays.asList("aa", "bb", "cc");
        Stream<String> stream = list.stream().map(String::toUpperCase);
        System.out.println(Arrays.toString(stream.toArray()));

        //练习：获取员工姓名长度大于三的员工
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<String> stream1 = employees.stream().map(Employee::getName);
        Stream<String> stream2 = stream1.filter(name -> name.length() > 3);
        System.out.println(Arrays.toString(stream2.toArray()));

        //练习：
        Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::formStringToStream);
        streamStream.forEach(t -> t.forEach(System.out::print));

        //flatMap(Function f)：接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
        Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::formStringToStream);
        System.out.println(Arrays.toString(characterStream.toArray()));

        //mapToDouble(ToDoubleFunction f)：接收一个函数作为参数，该函数会被应用到每个元素上，产生一个新的 DoubleStream

        //mapToInt(ToIntFunction f)：接收一个函数作为参数，该函数会被应用到每个元素上，产生一个新的 IntStream

        //mapToLong(ToLongFunction f)：接收一个函数作为参数，该函数会被应用到每个元素上，产生一个新的 LongStream
    }

    //将字符串中的多个字符构成的集合转换为对应的Stream的实例
    public static Stream<Character> formStringToStream(String str) {
        ArrayList<Character> list = new ArrayList<>();
        for (Character c: str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

    //3.排序
    @Test
    public void test3() {
        //sorted()：自然排序
        List<Integer> list = Arrays.asList(23, 234, 132, 24);
        Stream<Integer> sorted = list.stream().sorted();
        System.out.println(Arrays.toString(sorted.toArray()));

        //sorted(Comparator com)：定制排序
        List<Employee> employees = EmployeeData.getEmployees();
        //employees.stream().sorted(((o1, o2) -> Integer.compare(o2.getAge(), o1.getAge()))).forEach(System.out::println);
        //employees.stream().sorted(Comparator.comparingInt(Employee::getAge)).forEach(System.out::println);

        employees.stream().sorted(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                if (o1.getAge()==o2.getAge()) {
                    return Integer.compare(o2.getId(),o1.getId());
                }
                return -Integer.compare(o1.getAge(), o2.getAge());
            }
        }).forEach(System.out::println);
    }

}
